<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        //1.
                var a=10;
                var b=a;
                    a=20;
                console.log(b)//10 
                简单类型的先拷贝问题；相当于复制内容，不会相互影响；
        //1.1
                var a=b=0;
                    a=10;
                    b=20;
                    console.log(a,b)
                浏览器解析过程：
                    var a; 将b=0看成是a的值；先将a变量提升；
                    b=0;给b赋值；省略var的变量，会成为全局变量；
                    a=b;
                    a=10;//修改
                    b=20;//修改
                    console.log(a,b)//10 20 
        //1.2
                var a=b=c;//把b=c看成是a的值；
                    在没用var声明或没赋值时(省略var的创建变量)的变量时，会报错c is not defined
                    先变量提升：然后从右向左赋值
                        a=10;
                        b=20;
                        c=30;
                        console.log(a,b,c)
                    浏览器解析过程：
                        var a;  先变量提升
                        b=c;//浏览器执行到给b赋值时(省略了var)，没有找到c，直接报错c is not defined;
                        浏览器一旦报错后面代码不会执行；还没输出时就已经报错了；
                        a=b;
                        a=10;
                        b=20;
                        c=30;
                        console.log(a,b,c)
        //1.3
                    function fn(){
                        var a=b=1;//b省略了var，为全局变量；  a为局部变量   
                    }
                    fn()
                    console.log(a,b)//a is not defined；访问变量的规则
        //1.4
                    var a = b = 10;//a全局，b省略了var全局
                    　　(function(){

                    　　var a=b=20//a局部，b省略了var为全局变量

                    　　})();

                　　console.log(b);//20，在函数中修改成了20
        // 1.5
                function fn(a){此时a=100；
                        function a(){函数优先读取，此时a=function(){console.log(123)}
                            console.log(123)
                            }
                            a()再从上往下执行代码；
                        //先创建函数再调用、先调用再创建函数；浏览器都会优先读取函数，再从上往下执行代码，所以两者没区别
                        }
                        fn(100)
        //1.6
                var a=[]; 
                    b=[];   
                    c= a==b; 
                    console.log(c);  //c的值为a==b,输出false，是因为内存地址不一样
        //2.
                var a1={num:10};
                var a2=a1;
                    a1.num=20;
                console.log(a2.num)//20 
                复杂数据类型的先拷贝，相当于复制内容的地址，会相互影响；
        
        // 3.	加减法
                console.log(10+true)
                console.log(10+'1')
                console.log(10-'1')
                console.log(10-true)
                console.log('true'-'true')
                console.log(101-true+'true')
                console.log('101'-true-'true')
// 4.   转换布尔方法
                if(''){
                	console.log(1)
                }
                if(' '){
                	console.log(2)
                }
                if('false'){
                	console.log(3)
                }
                if(1-true){
                	console.log(4)
                }
                if([]){
                	console.log(5)
                }
                if({}){
                	console.log(6)
                }
// 5.	判断
                if(null==undefined){
                	console.log(1)
                }
                if(null===undefined){
                	console.log(2)
                }
// 6.  多个表达式
                var m=0;
                for(var i=20,j=10;i<25,j>2;i++,j--){
                    m=i*j 
                }
                console.log(i,j)
                console.log(m)
        //7.
            function f2(a,b){
                console.log(a+b)//30
            }//只是定义函数，调用函数的时候才会执行函数中的代码；
            console.log(a,b)//a is not defined
            var m=10;
            var n=20;
            f2(m,n)
            //浏览器在执行代码过程中，如果遇到报错，后面的代码不会执行
        //8.
            var a=10;
            var b=20;
            function f2(a,b){//10，20
                var p=a;//p=10
                    a=b;//a=20
                    b=p;//b=10;
                    console.log(a,b)//20,10
                    这里的a,b是函数的形参属于函数内部的变量
                }
                    f2(a,b)//这里传参的时候虽然用到了函数外部的a,b但只是用了a,b的值，相当于复制内容
                console.log(a,b)//10,20
        //9.
                var a=10;
                function fn(){
                    a=30;
                }
                fn()
                console.log(a)//10
                //变量的赋值：先从自己作用域中找，自己作用域中没有；
                //然后再去上一级找，上一级有，直接赋值就OK了
        //10 
                function f3(a,b){
                        var p=a.num;//p=10
                        a.num=b.num//a.num=20
                        b.num=p//b.num=10
                        console.log(a.num,b.num)//20,10
                    }
                var o1={num:10}
                var o2={num:20}
                f3(o1,o2)
                console.log(o1.num,o2.num)//20,10
                a与o1,b与o2指的都是同一个地址，如果起其中一个改了，会相互影响；
        //10.   区别：
                var a={'name':10}
                var p1=a.name;
                a.name=30;
                console.log(p1)//10
                复制内容

                var b={'name':30}
                var p2=b
                b.name=60;
                console.log(p2.name)//60
                复制地址；
        //11.
                function f4(a,b){ 
                return a+b
                }
                var rel=f4(10,30)
                console.log(rel)//40
        //12.
                var a = 10;
                    var b = 20;
                    function fn() {
                    var a = 10;
                    a++;//a=11 局部   单独变量算法
                    b--;//b=19 全局  单独变量算法
                    console.log(a)//11 局部
                    var c = a++ - --b;//a=12,b=18,c=-7  整个式子算法
                    console.log(c);//-7
                }
                fn();
                console.log(a);//10
                console.log(b);//18
                console.log(c);//c is not defined
        //13.
                var a = 10;
                var b = 20;
                function fn(a, b) {//a=10,b=20
                    a = a++ - b++;//a=11,b=21,a=-10
                    console.log(a, b);//-10,21
                } 
                fn(a, b);
                console.log(a, b)  //10,20
                //函数内部的变量相当于复制函数外部变量的内容，函数内部变量的改变并不会影响函数外部的变量；
        //14.
                var a = 10;
                var b = 20;
                function fn() {
                    console.log(a);//undefined  先访问自己作用域中的变量a a会先变量提升
                    var a = --b;//a=19,b=19   局部  自己没有去上一级访问b
                    c = a ++ + --b;//a=20,b=18,c=37    全局
                    c变量的赋值：一直到window都没有找到，会将c定义为全局变量，然后再赋值
                    console.log(a, b, c);//20,18,37
                }
                fn();
                console.log(a);//10
                console.log(b);//18
                console.log(c);//37
        //14.1
                var j=1;
                j=j+1;//相当于给j赋值为j=1+1
                alert(j);//2
        //14.2
                14.2
				var j=1;
				j=j++;//相当于给j赋值为j++; j++计算的整个式子结果为1，那么就是赋值为1
				alert(j);//1
        //14.3
                var j=1;
                j+=j++; //相当于给j加等于一个值， j++计算的整个式子结果为1，那么就是加等于1
                alert(j);//2
        //14.4
                var j=1;
				j+=++j;//相当于给j加等于一个值，++j计算的整个式子结果为2； 那么就是加等于2；
				alert(j);//3
        //14.5
                var j=1;
                j=(j--)+j+(j++)+(--j)+j;//考虑到变量i一直变化的问题；
                alert(j); //1
        //14.6
                // 求1：var a=1,b=2,c=3; console.log（a++ + b++ + ++b+a + --c+3）;
        //15.5
                var a = 10;
                var b = 20;
                function fn() {
                    c = a++ + ++b;//undefined+undefined nan会转为数值nan,nan与任何数值操作都得nan;
                    var 的变量提升不受if的限制；
                    if (c % 2 == 0) {//条件不成立，走else
                        var a = 30;
                    }else {
                        var b = 40;//局部
                    }
                    d  = --b - a--;//b=39,a=undefined c=nan
                    c和d应用了赋值的规则；
                    console.log(a)//nan
                    console.log(b)//39
                    console.log(c)//nan
                    console.log(d)//nan 
                }
                fn();
                console.log(a)//10
                console.log(b)//20
                console.log(c)//nan
                console.log(d)//nan
        //16.
                var a = 10;
                function a(){
                    console.log(a);
                }
                a();//a is not a function
                函数的变量提升，会被变量赋值之后覆盖；
        //17.
                var f1 = 20;
                var f1 = function () {
                    console.log(1);
                }
                f1();//1
                var a = 10;
                var a = 'hello';
                console.log(a);//hello
                覆盖
        //17.
                console.log(a); //a=function(){} 
                console.log(a()); //10
                function a() {
                        console.log(10)
                }
                var a = 3;
                console.log(a) //3
                a = 6;
                console.log(a());//a is not a function
                用console.log输出一个调用的函数时，浏览器执行函数会从上往下执行代码，
                执行到最后时，就会去找return返回值：不写return的时候，该函数的返回值是undefined;
        //18.
                var a=10;
                var b=20;
                function fn(){
                    a=--b;//a=19全局  b=19全局
                    b=a++;//b=20全局  a=20全局
                    (function(){//自执行函数
                        a--;//nan
                        b++;//b=21
                        if((a+b)%2==0){//nan%20==0 不符合条件，执行else
                            var a=20;
                        }else{
                            b=30;//b=30 全局变量
                        }
                    })();
                    c=--a - --b;//a=19全局变量a,b=29,c=-10 全局变量
                    console.log(a)//19
                    console.log(c)//-10
                }
                fn();
                console.log(a)//19
                console.log(b)//29
                console.log(c)//-10
//有关this指向的：
        // 19.
            function fn(){
            console.log(this)
            }
            fn()//window
            //只看函数的调用，与函数的定义无关；
            //全局调用：函数名()  this指向window
        //20.
            var name='window';
            function fn(){
            	console.log(this.name)
            }
            var o={
            	name:"zhang3",
            	fn:fn
            }
            fn();//window
            o.fn();//zhang3
            //只看函数的调用，与函数的定义无关；
            //定义在全局中的变量与函数会成为window的属性或方法
        // 21.
            var a=10;
            var b=20;
            function fn(){
                if((a++ + --b)%2==0){
                    //连串运算中a并没有改变，因为是先带入的运算，后自增1的，此时的a不变；--b是先自减再带入运算；所以此时b为19
                    //单独查看a变量的值：不管是++a还是a++都会自增1，此时的a为11；--b不管是--b还是b--都会自减1；
                    //条件中的10+19%2==0明显不正确，所以不会走if路径；，所以去走else路径；
                    this.a++
                }else{
                    this.b--
                }
            }
            fn();
            console.log(a);//11
            console.log(b);//18
            //计算自增或自减时：
                    //连串运算时，++a，先自增在运算；a++先带入运算再自增；
                    //单独查看某个变量时：不管是++a还是a++，都会自增1；
        //21 call和apply
            function fn(a,b){
                console.log(this)//10;10
                console.log(a,b)//20 undefined; 100 200
            }
            fn.call(10,20)
            fn.apply(10,[100,200])
            //call&&apply:第一个参数都是this的指向，第二个参数都是给函数传的参；
            //不同的是：call第二个参数以后是以序列的方式给函数传的参；
                    //apply第二个参数是以数组的方式给函数传参；
            //不传参，默认为undefined；
        //22.
            var a=10;
            var b=20;
            function fn(){
                //执行到函数中的代码时，先定义变量var b;此时b的值为undefined;
                //连串计算时：a的值不变，b的值--undefined为NaN，；
                //单独查看变量时，a=11,
                //因为If中的条件不符合，所以执行else中的；
                //走到else中，给b赋值，--a为10，b的值就赋值为了10 此时的b是局部变量；
                if((a++ + --b)%2==0){
                    this.a++; 
                }else{
                    var b=--a//b=10,a=10;
                }
            }
            fn()
            console.log(a)//10
            console.log(b)//20  不能访问函数中的变量，所以这里访问的是全局变量b;
            //调用函数时，才开始执行函数中的代码；
            //执行函数中的代码时，先找有没有定义的函数或变量，如果有的话先变量提升；再从上往下执行代码；
        // 23.
            var a=10;
            function fn(){
                c=--a;//a=9,c=9
            }
            fn()
            console.log(this.a)//9
            console.log(this.c)//9
            //定义在全局中的变量会成为window的属性；
            //在函数中不带var 的变量，会成为window的属性；
            //console中的this执行window，实际就是window.a,window.b
        //25. let变量
            {
            var a=10;//全局
            let b=20;//局部
            console.log(b)//20
            }
            console.log(a)//10
            console.log(b)//is not defined
            //var 声明的变量根据函数划分作用域
            //let声明的变量根据{}划分作用域
            //全局环境中不能访问局部变量；
        //26. 函数中的this指向
            var name='window';
            let o1={
                name:'zhang3',
                action:function(){
                    console.log(this.name)
                    //this指向o1 实际就是o1.name就是zhang3
                }
            }
            o1.action()
            //对象调用函数，点前面的是谁，就是谁调用的；
        //27.
                let o2={
                    name:'li4',
                    action:()=>{
                        console.log(this.name)//返回空,指向上一级中的this为window 默认的window.name为空
                        console.log(this)//window 
                    }
                }
                o2.action();
        // 28. 
                 let o3={
                    name:'li4',
                    action:function(){
                        (function(){
                            console.log(this.name)//返回一个空 自执行函数中的this指向window  window.name默认为空
                        })()
                    }
                }
                o3.action()
        //29.
                let o4={
                    name:'wang5',
                    action:function(){
                        (()=>{
                                console.log(this.name)//wang5,箭头函数中的this指向上一级中的this，o4.name为wang5
                            }
                        )()	
                    }
                }
                o4.action()
        //30.
                let o5={
                    name:'zhao6',
                    action:()=>{
                        (()=>{
                            console.log(this.name)//返回空，
                            //箭头函数中的this指向上一级作用域中的this，而上一级作用域也是个箭头函数，this指向上一级作用域中的this->window;
                            //所以此箭头函数中的this指向window，window.name默认为空；
                        })()
                    }
                }
                o5.action()
        //31.
                let o6={
                    name:'zhou7',
                    action:function(){//this指向o6
                        let fn=function(){
                            console.log(this.name)//zhou7
                        }
                        fn.call(this)//将fn函数中的this修改成此函数中的this->o6
                    }
                }
                o6.action()
        //32.
                let o7={
                    name:'wu8',
                    action:()=>{//this指向上一级作用域中的this->window 
                        let fn=function(){
                            console.log(this.name)//返回空，window.name默认值为空
                        }
                        fn.call(this)//将fn函数中的this指向修改成此函数中的this->window 
                    }
                } 
                o7.action()
        //33.   函数的默认值
                function f1(a,b){
                    console.log(a,b)
                }
                f1(10,20)//10，20
                f1(10)//10，undefined  不传参默认为undefined
                f1(10,20,30)//10，20  形参按顺序接收实参的值
        // 36.
                function f2(a,b=30){
                    console.log(a,b)
                }
                f2()//undefined,30  如果不传参并且没有默认值为undefined;如果不传参有默认值就用默认值30
                f2(1,2)//1,2 如果传参了就用传的参，不使用默认值；
        //37.
                function f3(a=1,b=2){
                    console.log(a,b)
                }
                f3(null,undefined)//null,2,
                如果传参了就用传的参数
                如果没有传参或传undefined，如果有默认值就用默认值，没有默认值就是undefined;
        //38.
                let x=10;
                function f4(a,b=x){
                    var x=5;
                    console.log(a,b)
                }
                f4()//undefined,10
        函数默认值参数：独立作用域;
        独立作用域中的访问变量时：
            独立作用域中如果没有创建该变量就去上一级中找变量，如果有直接使用；
            如果没有就再去上上级找，直到widnow都没有，会返回变量 is not defined;
        //39.
                let x=10;
                function f4(a,b=x){
                    let x=20;
                    console.log(a,b)//undefined 10   独立作用域的规则
                    console.log(x)//20  作用域中的变量访问的规则
                }
                f4()
        //40.
                	function f4(a,b=a){
                    	console.log(a,b)
                    }
                    f4(10)//10，10
        //41.
                let a=20;
                function f4(a,b=a){
                    console.log(a,b)
                }
                f4(10)//10 10
                f4()//undefined undefined
        //42.
                {
                    var a=10;  //var声明的变量 根据函数划分作用域
                    let b=20;//let声明的变量根据{}划分作用域
                    console.log('hello')//hello
                    console.log(b)//20
                }
                console.log(a)//10
                console.log(b)//b is not defined 作用域的限制
        //43.
                {
                var a=10;
                var a='20';
                console.log(a)//20
                let b=20;
                let b='hello'
                console.log(b)//报错  let声明的变量不能重复定义
                }
        //43.
                for (let i = 0; i < 10; i++) {
                console.log(i);
                }
                console.log('aaa');
                console.log(i); // i is not defined
                for循环中的{}是变量i的作用域；这是作用域的限制问题
        //43.
                function func1(arg) {
                let arg; 
                }
                let声明的变量不能重复定义：arg变量已经定义成了形参了，就不能在函数中再次定义了
        //44.
                let b='hello';
                    {
                        var a=10;
                        var b='20';//报错，let声明的变量不能重复定义；
                        console.log(a)

                        let b=20;
                        console.log(b)
                    }
        // 44.
                    function f1() {//这是一个私有的作用
                    let n = 5;
                    if (true) {//这是一个私有的作用域
                    	let n = 10;
                    }
                    console.log(n); // 5  作用域的限制
                    } 
                    f1()
        //45.
                {
                    let a=20;//let声明的变量不能重复定义
                    var a='10';
                    console.log(a)//报错  
                
                    var b='10';
                    let b=20;
                    console.log(b)
                }
        //46.
                {
                	console.log(a)//undefined  var 的变量提升
                	var a=10;
                	console.log(b)//报错，let声明的变量没有域解析
                	let b=20;
                }
        //47.
                let b='hello'
                {
                    console.log(b)//报错，let声明的变量没有域解析，也就是说不能先使用后声明
                    let b=20;
                    console.log(b)//20
                }
        //48.
                let a=10;
                a=20;//a=20
                a++;//a=21
                a='hello'//a=hello
                let b='hello'//
                {
                    console.log(a)//报错，let声明的变量不能重复定义
                    var a=10;
                }
        //49.
                let a=10;
                    a=20;
                    a++;
                    a='hello'
                    let b='hello'
                    {
                        console.log(a)//报错，let声明的变量没有域解析，也就是说不能先使用后声明
                        let a=10;
                    }
        //50.
                //函数参数的解构赋值
                function f1({x=0,y=0}={}){ 
                    console.log(x,y)
                }
                function f2({x,y}={x:0,y:0}){//参与了函数的默认值；
                    console.log(x,y)
                }
                //将{x=0,y=0}={}和{x,y}={x:0,y:0}看成函数默认值的写法；

                f1()//0 0 
                    //函数的默认值：调用函数时没有传参，就用默认值；{x=0,y=0}={}直接解构赋值
                f2()//0 0 
                    //函数的默认值：因为调用函数时没有传参，就用默认值：{x,y}={x:0,y:0}直接解构赋值
                f1({})//0 0
                    //函数的默认值：调用函数时传参了，就使用传的参；{x=0,y=0}={}进行解构赋值；
                    //对象的解构默认值：{x=0,y=0}={}：当变量取值为undefined或没有值时，都为undefined；
                f2({})//undefined undefined
                    //先计算函数的默认值：因为调用函数时传参了{}，就使用传的参进行解构赋值：{x,y}={}
                    //再计算对象解构赋值的默认值：{x,y}={}进行解构赋值：当变量取值为undefined或没有值时，都为undefined；
		//50.1
                let [head, ...tail] = [1, 2, 3, 4];
                console.log(head); // 1
                console.log(tail); // [2, 3, 4] 
                ...arr合并运算符，把剩余的元素合并；
        // 50.2
                解构赋值的默认值
                let [x2, y2, ...z2] = ['a'];
                console.log(x2); // 'a'
                console.log(y2); // undefined
                console.log(z2); // []
        //50.3
                var [foo3] = [];
                var [bar4, foo4] = [1];
                console.log(foo3);  // undefined
                console.log(bar4);  // 1
                console.log(foo4);  // undefined
        //50.4
                let [x3, y3] = [1, 2, 3];
                console.log(x3); // 1
                console.log(y3); // 2
        //50.5
                let [a2, [b2], d2] = [1, [2, 3], 4];
                console.log(a2); // 1
                console.log(b2); // 2
                console.log(d2); // 4
        //50.6
                // 报错
                let [f] = 1;
                let [f] = false;
                let [f] = NaN;
                let [f] = undefined;
                let [f] = null;
                let [f] = {};
                // 解构赋值必须是相对应的{}与{}、[]和[]
        //50.7
                var [foo = true] = [];
		        console.log(foo); // true
        // 50.8
                var [x, y = 'b'] = ['a'];
                console.log(x); // a
                console.log(y); // b
        //50.9
                var [x2, y2 = 'b'] = ['a', undefined];
                console.log(x2); // a
                console.log(y2); // b

                function f() {
                console.log('aaa');
                }
                let [x2 = f()] = [1]; 
                console.log(x2); // 1

                //对象的解构赋值
                var { foo, bar } = { foo: 'aaa', bar: 'bbbb'};
                console.log(foo); // aaa
                console.log(bar); // bbbb
        //51.  var 和function变量提升的问题
                var num=1;
                var fn=function(){
                    console.log(num);
                    var num=123;
                }
                function fn(){
                    console.log(num+321)
                }//覆盖掉了
                fn()//undefined
        //52.
                    var num=123;
                function f1(){
                    console.log(num)//123
                }
                function f2(){
                    var num=456
                    f1()
                }
                f2()
                console.log(num)//123
                作用域只跟函数的定义有关系，与函数的调用没有关系；
        //54.
                var num;
                function num(){
                } 
                console.log(num)//num=function(){}
        //55.
                var a = 10;
                function test() {
                　　a = 100;//局部
                　　console.log(a);//100
                　　console.log(this.a);//10  全局
                　　var a;
                　　console.log(a);//100  局部
                }
                test();
        //56.
                var a = 100;
                function test(){
                　　console.log(a);//undefined  局部a变量提升
                　　var a = 10;
                　　console.log(a);//10   赋值之后
                }
                test();
        //57.
                var a = 100;
                function test(){
                　　console.log(a);//100
                　　a = 10; 
                　　console.log(a);//10
                }
                test();
        //58.
                function fn(){
                    a=12 
                    console.log(window.a)//12
                }
                fn()
        //59.
                console.log(a);//undefined  全局a变量提升
                var a = 12;
                function fn(){
                    console.log(a);//undefined  局部a变量提升
                    var a = 13;
                }
                fn();
                console.log(a); //12
        //60.
                console.log(a);//undefined  全局a变量提升
                var a = 12;
                function fn(){
                    console.log(a);//12  自己作用域中没有，去上一级作用域中找
                    a = 13;//赋值，自己作用域中没有，去上一级作用域中找；
                }
                fn();
                console.log(a);//13  在全局作用域中访问变量的时候，要注意看局部作用域中有没有进行对全局变量的赋值；
        //61.
                console.log(a);//a is not defined 全局作用域中a没有var 所以没有变量提升
                a = 12;
                function fn(){
                    console.log(a);//12  给全局变量a赋值
                    a = 13;//给全局变量a赋值
                }
                fn();
                console.log(a);//13
        //62.
                function a(){//function和var 函数优先置顶
                console.log(1)
                }
                var a=20; //给变量a赋值，覆盖了函数
                console.log(a)//20
        //63.
                console.log(a);//undefined
                var a = 10;
        //64.
                foo();
                function foo() {  //因为function会被浏览器优先读取
                    console.log("aaa");//aaa
                }
                说明了声明式函数可以先调用，后定义；
        //65.
                foo();//foo is not a function
                var foo = function() {//把整个式子看成var的变量提升
                    console.log("aaa");
                }
                说明了赋值式函数不可以先调用后定义；
                浏览器执行：
                    var foo;
                    foo()
                    var foo=function(){
                        console.log('aaa')
                    }
        //66.
                var foo;
                console.log(foo);//undefined
                foo(); //foo is not a function
                foo = function() {
                    console.log("aaa");
                }
        //67.
                console.log(foo);//f foo(){}
                var foo = 10;
                console.log(foo);//10
                function foo() {
                    console.log(10);
                }
                console.log(foo);//10
                var和function 函数优先置顶，并且会被变量赋值覆盖
        //68，
                var b = 10;
                    b = 10;
                    console.log(b);//10 
        // 69.
                var b = 10;
                    b = 20;
                    console.log(b);//20
        //70.
                setInterval(function(){
                	console.log(10)
                })
                console.log(20)
				//20 
				//10...
                定时器是一个多线程：定时器都有个等待的时间，等待的过程中并不会影响后续代码的执行
        //71.
                var v1=1;
                function level1(){
                    var v2=2;
                    function level2(){
                        var v3=3;
                        function level3(){
                            var v4=4;
                            console.log(v1,v2,v3,v4)//1,2,3,4
                        }
                        level3()
                    }
                    level2()
                }
                level1()
        //72.
                var foo=3;
                function bar(){
                    var foo=foo||5;//逻辑或的规则
                    console.log(foo)//5
                }
                bar()
        //74.
                    function bar(){
                    function foo(){
                        console.log(2)
                    }
                    var foo
                    foo()//2
                    foo=function(){
                        console.log(1)
                    }
                    foo()//1
                    foo()//1
                }
                bar()
        // 75.
                function foo () {
                    console.log(bar)//undefined
                    var bar=456
                    console.log(bar)//456
                }
                foo()
        //77.
               	var foo=1
                function bar() {
                   if(!foo){//!undefined !false=true
                       var foo=10
                   }
                    console.log(foo)//10
                }
                bar() 
                var的变量提升不受if的限制
        //78.
                const arr=[];
                for(var i=0;i<3;i++){
                    arr.push(function(){
                        console.log(i)
                    })
                }
                arr[0]()//0
                arr[1]()//1
                在for循环中，每循环一次i，arr就尾项添加一次函数，但并没有执行函数中的代码；因为没有调用；
                for循环执行完成后才调用的函数，这时再执行函数中的代码: 
                    i是全局变量，每循环一次i就赋值一次；最后i=3时，不符合条件才跳出循环；
                    这时再调用函数，就是i了；
        //79.
                    const arr=[];
                    for(var i=0;i<3;i++){
                        arr.push(function(){
                            console.log(i)
                        })
                    }
                    arr[0]()//3
                    arr[1]()//3 
                用var 声明的变量根据函数划分作用域；那么这里的i就是全局作用域；
                在循环的过程中不会执行函数的代码，调用时才会执行；
                {
                    i=0;
                    arr.push(function(){
                        console.log(i)
                    })
                }
                {
                    i=1;
                    arr.push(function(){
                        console.log(i)
                    })
                }
                ...
                arr[0]()//3
                arr[1]()//3 
                i循环到3，不符合条件结束循环；
                调用了函数执行函数中的代码；访问i变量，自己作用域中没有，去上一级作用域中找，有直接使用，
                此刻的i已经是3了
        //80.
                const arr=[];
				for(let i=0;i<3;i++){
					arr.push(function(){
						console.log(i)
					})
				}
				arr[0]()//0
				arr[1]()//1
				用let声明的变量根据{}划分作用域；for循环中每循环一次的{}就是一个单独的作用域；
				{
					i=0;
					arr.push(function(){
						console.log(i)
					})
				}
				{
					i=1;
					arr.push(function(){
						console.log(i)
					})
				}
				...
				调用函数时，执行函数中的代码，又因为作用域与函数的定义有关系；
				所以访问i变量时使用自己作用域中的变量i;
//90.
        变量提升不受if语句的控制；所以用var声明的变量a会变量提升；为全局变量；
            if(false){括号中为false,所以不走if中的内容；
				var a = 1;
				let b = 2;//用let声明的变量根据{}划分作用域，为局部变量
			}
			console.log(a);//undefined
			console.log(b);//b is not defined
//91.
            var a = 1;
            if(true){//if括号中为true,走if中的内容
                console.log(a);
                let a = 2;//访问变量会先访问自己作用域中的，自己作用域中有，先使用自己作用域中的变量，又因为let声明的变量不会变量提升，所以报错；
            }
//92.
            var a = {n: 1}
            var b = a
            a.x = a = {n: 2}
            console.log(a.n, b.n);
            console.log(a.x, b.x);
            因为var b=a;所以此时a和b指同一个对象；
            .运算符比 = 运算符高,先计算`a.x`;
            b={
                n:1,
                x:undefined
            }
            从右向左赋值：a={n:2};
            此时再给a.x赋值：
                b={
                    n:1,
                    x:{
                        n:2,
                    }
                }
            a={
                n:2,
            }
//93.1
            var x=10;
                bar()
                function bar(){
                    var x=30;
                    function foo(){
                        console.log(x)//访问变量，先从自己作用域中找，没有就去上一级作用域中找
                    }
                    foo()
                }
//93.2
                var fn=1;
				function fn(){
					console.log(fn)
				}
				fn()//fn is not a function
//94.
            var x=10;
                bar()
                function foo(){
                    console.log(x)//10 作用域中与函数的定义有关，与函数的调用没关系；
                }
                function bar(){
                    var x=30;
                    foo()
                }
//95.
                function fn(){
					console.log(a)//5
				}
				function fn1(){
					var a=1;
					fn()
				}
				var a=2;
				a=5;
				fn1()
                a=4
//95.
                var a=1;
                    function fn1(){
                        function fn3(){
                            function fn2(){
                                console.log(a)//undefined
                            }
                            var a; 变量会声明；
                            fn2()
                            var a=4;//如果将这个放在fn2()的前面就输出4了
                        }
                        var a=2;
                        return fn3
                    }
                    var fn=fn1()//fn其实就是函数fn3
                    fn()
//96.
                var a=1;
                    function fn1(){
                        function fn2(){
                            console.log(a)
                        }
                        function fn3(){
                            var a=4;
                            fn2()
                        }
                        var a=2;
                        return fn3
                    }
                    var fn=fn1()
                    fn()
//97.
                                        var k = 1;
                                        if (1) {//1为非0和NaN,会返回true
                                        function foo(){};
                                        k += typeof foo;//1+='function'
                                        //typeof判断一个函数会返回function
                                        }
                                        console.log(k); //1function
                    //98
                                        var y = 1;
                                        if (function f(){}) {//会返回true；
                                        y += typeof f;//1+=undefined
                                        //函数声明写在运算符中，其为 true，但放在运算符中的函数声明在执行阶段是找不到的
                                        //typeof 判断一个没有定义的变量会返回undefined
                                        }
                                        console.log(y);//1undefined
                    //99.
                                        var x = { foo : 1};
                                    var output = (function(){
                                    delete x.foo;//delete可以将对象中的foo属性删除
                                    return x.foo;
                                    })();
                                    console.log(output);//undefined
                    //100
                                    var x = 1;
                                var output = (function(){
                                delete x;//delete 只能删除对象中的属性，但不能删除变量；所以变量x没有被删除
                                return x;
                                })();
                                console.log(output);//1
                    //101
                                    var output = (function(x){//x=0;
                                    delete x;//delete只能删除对象中的属性，但不能删除变量，所以变量没有被删除
                                    return x;
                                })(0);
                    // 101.2
                                var trees=['xyz','xxx','test','ryan','apple'];
                                delete trees[3];
                                console.log(trees.length);//5
                                //delete删除数组中的某个元素，会保留原来的位置；
                    //102
                            console.log(mul(2)(3)(4)); //24
                            console.log(mul(4)(3)(4)); //48
                            //一层一层的调用函数；内部函数总是可以访问其所在的外部函数中声明的参数和变量
                            function mul (x) {
                            return function (y) {
                            return function (z) { 
                            return x * y * z; 
                            };
                        };
                    }
                //103.
                        var obj1 = {a:1,b:2}
                        var obj2 = {a:1,b:2}
                        console.log(obj1 == obj2) //flase就算是属性都一样，地址也不一样；
                        console.log(obj1 = obj2) //{a:1,b:2}将obj对象的地址赋值给obj1；console中的代码会被执行；这时obj1等于了obj2了
                        console.log(obj1 == obj2) //true;
                        console.log(a=1);
                        console.log(a)
                //104.
                        var a = 1
                        var c = {
                            name: 'nima',
                            age: 2
                        }
                        function f1(n){
                            ++n
                        }
                        function f2(obj){
                            ++obj.age
                        }

                        f1(a)//相当于传了个内容
                        f2(c)//相当于传了个地址；都是指一个地址
                        f1(c.age)//传了个内容
                        console.log(a) //1
                        console.log(c) //{'name':'nima',age:3;}
//105.
                                // console.log(1+2+'3')//33
                                // console.log('3'+2+1)//321
                                // console.log(3+4+'5'+5+1)//7551
                                // console.log(+'3'+2+1)//6
                                // console.log(1+ +'3'+2+1)//7
                                // console.log(1+ +'2'+'3')//33
                                // console.log('A'-'B'+'C')//NaNC
                                // console.log('C'+'A'-'B')//NaN
// 106.
                                // console.log(0&&2||1)//1
                                // console.log(0||2&&1)//1
                                // console.log(0&&2&&3||1||4)//1
                                // console.log(0||2||3&&1)//2
                                // console.log(0||2||3&&1&&4)//2
                                // //因为&&的比||的优先级高,遇到&&从左向右计算，最后再从左向右计算||
                                // console.log(0||1||2)//1
                                // console.log(0||1||2||3)//1
                                // console.log(0&&2&&1)//0
                                // console.log(0&&2&&1&&3)//0
// /107.
                            // var a=0.1,b=a+++a,c=a--+b;
	                        // console.log(a,b,c)//0.1,2.2,2.3
//108.
                                // (function(){
									// 	var a=b=9;
									// })();
									// 	console.log(a);//a is not defined报错后面的代码不会执行；
									// 	console.log(b);//9
// 109.
                        // function aa() {
						// 		var a=b=9;
						// 	}
						// 	console.log(a);//a is not defined 报错后面的代码不执行；
						// 	console.log(b);//b is not defined  因为没有调用函数，不会执行函数中的代码；
//110.
						// function aa() {
						// 		var a=b=9;
						// 		console.log(a);//9
						// 		console.log(b)//9
						// 	}
						// 	aa()
//111.
						// function aa() {
						// 		var a=b=c=9;//b,c为全局变量
						// 		console.log(a);//9
						// 		console.log(b)//9
						// 		console.log(c)//9
						// 	}
						// 	aa();
						// 	console.log(a);//a is not defined 报错后面的代码不执行
						// 	console.log(b);//9
						// 	console.log(c);//9
//112.
                // var counter=function(){
				// 			var count=1;
				// 			return function(){
				// 				return count++
				// 			}
				// 		}
				// 		var c=counter();
				// 		console.log(c())//1
				// 		console.log(c())//2
				// 		console.log(c())//3	
//113. 
                // 问题：以下哪条语句会产生运行错误：
                // A.var obj = ();//语法错误 
                // B.var obj = [];//创建数组 
                // C.var obj = {};//创建对象 
                // D.var obj = //; 创建正则
                //答案：A
//114. 
                const value={
                        number:10
                    }
                    const multiply=(x={...value})=>{
                        console.log(x.number*=2)
                    }
                    multiply()//20
                    multiply()//20
                    //不传参时使用默认参数，前两次调用都是使用的默认参数，每次调用都是创建了一个新的默认参数；
                    multiply(value)//20
                    multiply(value)//40
                    //当传参时使用传的参数是全局变量为复杂数据类型，每次调用都是使用的同一个地址；
//119. 
                    var a={
                            i:1,
                            valueOf(){
                                return this.i++
                            }
                        }
                        if(a==1&&a==2&&a==3){
                            console.log(1)
                        }
//121. 
      //将2维数组转1维数数组  
                var arr=[1,[2,[3,4,2],2],5,[6]];
                        function fn(arr){
                            var arr1=[];
                            arr.forEach(item=>{
                                if(Array.isArray(item)){
                                    arr1.push(...fn(item))
                                }else{
                                    arr1.push(item)
                                }
                        })
                        return arr1
                    }
                        console.log(fn(arr))
//121 
                var x=1,y=z=0;
                function add(n){
                    return n=n+1;
                }
			    y=add(x)
				function add(n){
					return n=n+3
				}
                z=add(x);
                console.log(add(x))
                //后面函数覆盖前面函数；
    </script>
    
    </script>
</body>
</html>